package com.wg.core.io;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import com.wg.core.utils.BitConverter;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 大端序二进制数据读取器实现
 *
 * <p>实现IBinaryReader接口，提供大端序格式的二进制数据读取功能</p>
 *
 * @author 少爷123
 */
public class BigEndianBinaryReader implements IBinaryReader {
    private static final int MAX_SHORT_LENGTH = 0x7fff;
    private static final int LONG_STRING_MARKER = -1;

    private final ByteArrayInputStream stream;

    /**
     * 通过字节数组构造读取器
     *
     * @param bytes 要读取的字节数组
     */
    public BigEndianBinaryReader(byte[] bytes) {
        this.stream = new ByteArrayInputStream(bytes);
    }

    /**
     * 通过字节输入流构造读取器
     *
     * @param stream 字节输入流
     */
    public BigEndianBinaryReader(ByteArrayInputStream stream) {
        this.stream = stream;
    }

    /**
     * 从流中读取指定长度的字节
     *
     * @param length 要读取的字节长度
     * @return 读取的字节数组
     * @throws IllegalStateException 当可用字节不足时抛出
     */
    private byte[] readBytesFromStream(int length) {
        if (stream.available() < length) {
            throw new IllegalStateException("Insufficient bytes available: required "
                    + length + ", available " + stream.available());
        }

        byte[] buffer = new byte[length];
        int bytesRead = stream.read(buffer, 0, length);
        if (bytesRead != length) {
            throw new IllegalStateException("Failed to read requested bytes: expected "
                    + length + ", read " + bytesRead);
        }
        return buffer;
    }

    // ===================== 布尔类型实现 =====================

    @Override
    public boolean readBoolean() {
        return BitConverter.toBoolean(readBytesFromStream(1));
    }

    @Override
    public boolean[] readBooleanArray() {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        boolean[] value = new boolean[len];
        for (int i = 0; i < len; i++) {
            value[i] = readBoolean();
        }
        return value;
    }

    @Override
    public List<Boolean> readBooleanCollection() {
        return readCollection(this::readBoolean);
    }

    // ===================== 字节类型实现 =====================

    @Override
    public byte readByte() {
        return readBytesFromStream(1)[0];
    }

    @Override
    public byte[] readBytes(int length) {
        return readBytesFromStream(length);
    }

    @Override
    public byte[] readBytesWithLength() {
        int len = readInt();
        return readBytes(len);
    }

    @Override
    public byte[] readRemainingBytes() {
        return readBytes(stream.available());
    }

    // ===================== 字符类型实现 =====================

    @Override
    public char readChar() {
        return BitConverter.toChar(readBytesFromStream(2));
    }

    @Override
    public char[] readCharArray() {
        int len = readShort();
        if (len < 0 || len > MAX_SHORT_LENGTH) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        char[] value = new char[len];
        for (int i = 0; i < len; i++) {
            value[i] = readChar();
        }
        return value;
    }

    // ===================== 双精度浮点实现 =====================

    @Override
    public double readDouble() {
        return BitConverter.toDouble(readBytesFromStream(8));
    }

    @Override
    public double[] readDoubleArray() {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        double[] value = new double[len];
        for (int i = 0; i < len; i++) {
            value[i] = readDouble();
        }
        return value;
    }

    @Override
    public List<Double> readDoubleCollection() {
        return readCollection(this::readDouble);
    }

    // ===================== 短整型实现 =====================

    @Override
    public short readShort() {
        return BitConverter.toShort(readBytesFromStream(2));
    }

    @Override
    public short[] readShortArray() {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        short[] value = new short[len];
        for (int i = 0; i < len; i++) {
            value[i] = readShort();
        }
        return value;
    }

    @Override
    public List<Short> readShortCollection() {
        return readCollection(this::readShort);
    }

    // ===================== 整型实现 =====================

    @Override
    public int readInt() {
        return BitConverter.toInt(readBytesFromStream(4));
    }

    @Override
    public int[] readIntArray() {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        int[] value = new int[len];
        for (int i = 0; i < len; i++) {
            value[i] = readInt();
        }
        return value;
    }

    @Override
    public List<Integer> readIntCollection() {
        return readCollection(this::readInt);
    }

    @Override
    public BigInteger readBigInteger() {
        return new BigInteger(readString());
    }

    // ===================== 长整型实现 =====================

    @Override
    public long readLong() {
        return BitConverter.toLong(readBytesFromStream(8));
    }

    @Override
    public long[] readLongArray() {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        long[] value = new long[len];
        for (int i = 0; i < len; i++) {
            value[i] = readLong();
        }
        return value;
    }

    @Override
    public List<Long> readLongCollection() {
        return readCollection(this::readLong);
    }

    // ===================== 单精度浮点实现 =====================

    @Override
    public float readFloat() {
        return BitConverter.toFloat(readBytesFromStream(4));
    }

    @Override
    public float[] readFloatArray() {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        float[] value = new float[len];
        for (int i = 0; i < len; i++) {
            value[i] = readFloat();
        }
        return value;
    }

    @Override
    public List<Float> readFloatCollection() {
        return readCollection(this::readFloat);
    }

    // ===================== 字符串实现 =====================

    @Override
    public String readString() {
        short lenShort = readShort();
        int length;

        // 处理长字符串特殊标记
        if (lenShort == LONG_STRING_MARKER) {
            length = readInt();
        } else if (lenShort < 0) {
            throw new IllegalStateException("Invalid string length: " + lenShort);
        } else {
            length = lenShort;
        }

        // 检查可用字节是否足够
        if (stream.available() < length) {
            throw new IllegalStateException("Insufficient bytes for string: required "
                    + length + ", available " + stream.available());
        }

        byte[] buf = readBytes(length);
        return new String(buf, StandardCharsets.UTF_8);
    }

    @Override
    public String[] readStringArray() {
        return readObjectArray(String[]::new, this::readString);
    }

    @Override
    public List<String> readStringCollection() {
        return readCollection(this::readString);
    }

    // ===================== 可序列化对象实现 =====================

    @Override
    public <T extends IBinaryReadable> T readObject(Class<T> clazz) {
        T instance = ReflectUtil.newInstance(clazz);
        instance.readBytes(this);
        return instance;
    }

    @Override
    public <T extends IBinaryReadable> T[] readObjectArray(Class<T> clazz) {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        T[] array = ArrayUtil.newArray(clazz, len);
        for (int i = 0; i < len; i++) {
            array[i] = readObject(clazz);
        }
        return array;
    }

    @Override
    public <T extends IBinaryReadable> List<T> readObjectCollection(Class<T> clazz) {
        return readCollection(() -> readObject(clazz));
    }

    @Override
    public ByteArrayInputStream baseStream() {
        return stream;
    }

    // ===================== 通用读取方法 =====================

    /**
     * 读取对象集合
     *
     * @param <T>           集合元素类型
     * @param elementReader 元素读取函数
     * @return 对象集合
     */
    private <T> List<T> readCollection(ElementReader<T> elementReader) {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid collection length: " + len);
        }

        List<T> list = new ArrayList<>(len);
        for (int i = 0; i < len; i++) {
            list.add(elementReader.read());
        }
        return list;
    }

    /**
     * 读取对象数组
     *
     * @param <T>           数组元素类型
     * @param arraySupplier 数组创建函数
     * @param elementReader 元素读取函数
     * @return 对象数组
     */
    private <T> T[] readObjectArray(ArraySupplier<T[]> arraySupplier, ElementReader<T> elementReader) {
        int len = readShort();
        if (len < 0) {
            throw new IllegalStateException("Invalid array length: " + len);
        }

        T[] array = arraySupplier.create(len);
        for (int i = 0; i < len; i++) {
            array[i] = elementReader.read();
        }
        return array;
    }

    // ===================== 函数式接口定义 =====================

    @FunctionalInterface
    private interface ElementReader<T> {
        T read();
    }

    @FunctionalInterface
    private interface ArraySupplier<T> {
        T create(int length);
    }
}